package com.coolw.design.pattern.create.singleton;

/**
 * 懒汉式单例:类加载时没有生成单例，只有当第一次调用 getlnstance 方法时才去创建这个单例
 *
 * @author coolw
 * @date 2019-12-21 09:09
 */
public class LazySingleton {

    /**
     * 保证instance在所有线程中同步
     * <p>volatile: 保证了变量在内存中的可见性,防止指令重排序
     */
    private static volatile LazySingleton instance = null;

    /**
     * 私有化构造方法，避免类在外部被实例化
     */
    private LazySingleton() {
    }

    /**
     * 方式1-获取实例对象
     * <p>双重检查锁定懒汉式: 线程安全且高效(推荐使用)
     * <pre>
     * 1.当首次判断 null == instance 不成立时则直接返回,这一次是没有锁开销的
     * 2.当首次判断 null == instance 成立时会进入同步代码块,会再次判断一次 null == instance 来避免多个线程同时创建实例
     * </pre>
     *
     * @return instance
     */
    public static LazySingleton getInstance() {
        if (null == instance) {
            synchronized (LazySingleton.class) {
                if (null == instance) {
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }

    /**
     * 方式2-获取实例对象
     * <p>同步方法懒汉式: 线程安全不高效。synchronized 关键字保证了线程安全,但每次调用 getInstance() 方法都会进行同步(阻塞)
     * ,会带来一定的性能开销
     *
     * @return instance
     */
//    public static synchronized LazySingleton getInstance() {
//        if (null == instance) {
//            instance = new LazySingleton();
//        }
//        return instance;
//    }

    /**
     * 方式3-获取实例对象
     * <p>线程不安全(弃用): 在多线程情况下,可能会同时判断 null == instance 的情况,会导致创建多个 instance 实例,破坏单例性
     */
//    private static LazySingleton instance = null;
//    public static LazySingleton getInstance() {
//        if (null == instance) {
//            instance = new LazySingleton();
//        }
//        return instance;
//    }
}
